package com.csap.framework.oauth2.server.boot;

import cn.dev33.satoken.LoginUtil;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.oauth2.logic.SaOAuth2Template;
import com.csap.framework.boot.apidoc.autoconfigure.EnableApidoc;
import com.csap.framework.boot.web.autoconfigure.EnableEnum;
import com.csap.framework.extension.CsapException;
import com.csap.framework.oauth2.request.MobileRequest;
import com.csap.framework.oauth2.request.PasswordRequest;
import com.csap.framework.oauth2.server.Oauth2ServerProperties;
import com.csap.framework.oauth2.server.SaOauth2TemplateImpl;
import com.csap.framework.oauth2.server.listener.TokenListener;
import com.csap.framework.oauth2.server.login.spi.Oauth2LoginSpiMobile;
import com.csap.framework.oauth2.server.login.spi.Oauth2LoginSpiUserName;
import com.csap.framework.oauth2.server.service.ClientService;
import com.csap.framework.oauth2.server.service.Oauth2ServerService;
import com.csap.framework.oauth2.server.service.PlatformService;
import com.csap.framework.oauth2.server.service.UserOpenInfoService;
import com.csap.framework.util.CollectionsUtil;
import com.csap.framework.util.map.CsapMap;
import com.csap.mybatisplus.autoconfigure.typealiases.EnableTypeAliases;
import com.csap.mybatisplus.autoconfigure.xml.EnableMapperXml;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ModelAndView;

/**
 * oauth2 服务器
 *
 * @author yangchengfu
 * @dataTime 2021年-07月-25日 22:21:00
 **/
@Configuration
@EnableConfigurationProperties(Oauth2ServerProperties.class)
@ComponentScan("com.csap.framework.oauth2.server")
@ConditionalOnProperty(prefix = Oauth2ServerProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@MapperScan("com.csap.framework.oauth2.server.mybatis")
@EnableApidoc("com.csap.framework.oauth2.server")
@EnableTypeAliases("com.csap.framework.oauth2.server.entity")
@EnableEnum("cn.dev33.satoken.oauth2.logic.type")
@EnableMapperXml("classpath*:com/csap/framework/oauth2/server/mybatis/xml/*.xml")
public class Oauth2ServerAutoConfiguration {
    @Bean
    @ConditionalOnBean({ClientService.class, UserOpenInfoService.class, PlatformService.class})
    @ConditionalOnMissingBean(SaOAuth2Template.class)
    public SaOAuth2Template saOAuth2Template(ClientService clientService, UserOpenInfoService userOpenInfoService, PlatformService platformService) {
        return new SaOauth2TemplateImpl(clientService, userOpenInfoService, platformService);
    }

    @Bean
    @ConditionalOnMissingBean(SaTokenListener.class)
    public SaTokenListener saTokenListener() {
        return new TokenListener();
    }

    /**
     * OAuth2 定制化配置
     *
     * @param oauth2ServerProperties 配置参数
     * @param cfg                    cfg
     * @param oauth2ServerService    授权认证服务
     * @param oauth2LoginSpiUserName 授权登录-账号密码
     */
    @Autowired
    public void setSaOAuth2Config(Oauth2ServerProperties oauth2ServerProperties, SaTokenConfig saTokenConfig, SaOAuth2Config cfg, Oauth2ServerService oauth2ServerService, Oauth2LoginSpiUserName oauth2LoginSpiUserName, Oauth2LoginSpiMobile loginSpiMobile) {
        cfg.
                setNotLoginView(() -> new ModelAndView(oauth2ServerProperties.getNotLoginView())).
                setDoLoginHandle((u, p) -> oauth2ServerService.login(null, null, u, p)).
                setLoginHandle(i -> oauth2LoginSpiUserName.login(PasswordRequest.builder()
                        .userName(i.getUserName())
                        .deviceType(i.getDeviceType())
                        .password(oauth2ServerProperties.encry(i.getPassword()))
                        .build()
                        .loginType(i.getLoginType())
                        .platform(i.getPlatform())
                        .clientId(i.getClientId()))).
                setLoginSmsHandle(i -> {
                    loginSpiMobile.login(MobileRequest.builder()
                            .mobile(i.getUserName())
                            .deviceType(i.getDeviceType())
                            .platform(i.getPlatform())
                            .loginType(i.getLoginType())
                            .clientId(i.getClientId())
                            .build());
                    throw new CsapException("功能未实现");
                }).
                setConfirmView((clientId, scope) -> new ModelAndView(oauth2ServerProperties.getConfirmView(), CsapMap.<String, Object>build()
                        .add("clientId", clientId)
                        .add("scope", scope)));
        LoginUtil.init(CollectionsUtil.isEmpty(saTokenConfig.getLoginTypeMap()) ? CsapMap.<String, SaTokenConfig>build().add(saTokenConfig.getLoginType(), saTokenConfig) : saTokenConfig.getLoginTypeMap(), saTokenConfig);
    }
}
